home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / utils / xad / developer / sources / tools / xadunfile.c < prev   
C/C++ Source or Header  |  1999-01-01  |  13KB  |  432 lines

  1. #define NAME         "xadUnFile"
  2. #define DISTRIBUTION "(Freeware) "
  3. #define REVISION     "4"
  4.  
  5. /* Programmheader
  6.  
  7.     Name:        xadUnFile
  8.     Author:        SDI
  9.     Distribution:    Freeware
  10.     Description:    dearchives file archives
  11.     Compileropts:    -
  12.     Linkeropts:    -gsi -l amiga
  13.  
  14.  1.0   13.09.98 : first version
  15.  1.1   18.11.98 : added FILE parameter and directory creation
  16.  1.2   03.02.99 : added corrupt message
  17.  1.3   07.02.99 : added missing "group crunched" handling
  18.  1.4   16.03.99 : errors no longer abort decrunching
  19. */
  20.  
  21. #include <proto/xadmaster.h>
  22. #include <proto/exec.h>
  23. #include <proto/dos.h>
  24. #include <exec/memory.h>
  25. #include <dos/dosasl.h>
  26. #include <utility/hooks.h>
  27. #include "SDI_defines.h"
  28. #include "SDI_compiler.h"
  29. #define SDI_TO_ANSI
  30. #include "SDI_ASM_STD_protos.h"
  31.  
  32. struct xadMasterBase *    xadMasterBase = 0;
  33. struct DosLibrary *     DOSBase = 0;
  34. struct ExecBase *     SysBase  = 0;
  35.  
  36. #define PARAM    "FROM/A,DESTDIR,PASSWORD/K,FILE/M,NE=NOEXTERN/S,"     \
  37.         "INFO=LIST/S,OW=OVERWRITE/S,NOTREE/S,ASKMAKEDIR/S,"    \
  38.         "NOCOMMENT/S,NOPROT/S,NODATE/S,NOABS/S"
  39.  
  40. #define OPTIONS \
  41.   "FROM       The input archive file (no patterns allowed)\n"        \
  42.   "DESTDIR    The destination directory, not needed with INFO\n"    \
  43.   "PASSWORD   A password for encrypted archives\n"            \
  44.   "FILE       Multiple filenames (with patterns) to be extracted\n"    \
  45.   "NOEXTERN   Turns off usage of external clients\n"            \
  46.   "INFO       Shows archive information without extracting\n"        \
  47.   "OVERWRITE  Files are overwritten without asking\n"            \
  48.   "NOTREE     Files are extracted without subdirectories\n"        \
  49.   "ASKMAKEDIR You get asked before a directory is created\n"        \
  50.   "NOCOMMENT  No filenote comments are extracted or displayed\n"    \
  51.   "NOPROT     Protection information gets not extracted\n"        \
  52.   "NODATE     Creation date information gets not extracted\n"        \
  53.   "NOABS      Do not extract absolute path name parts\n"
  54.  
  55. struct xHookArgs {
  56.   STRPTR name;
  57.   ULONG flags;
  58.   ULONG finish;
  59. };
  60.  
  61. struct Args {
  62.   STRPTR   from;
  63.   STRPTR   destdir;
  64.   STRPTR   password;
  65.   STRPTR * file;
  66.   ULONG    noextern;
  67.   ULONG    info;
  68.   ULONG    overwrite;
  69.   ULONG    notree;
  70.   ULONG    askmakedir;
  71.   ULONG    nocomment;
  72.   ULONG    noprot;
  73.   ULONG    nodate;
  74.   ULONG    noabs;
  75. };
  76.  
  77. ASM(ULONG) progrhook(REG(a0, struct Hook *),
  78.   REG(a1, struct xadProgressInfo *));
  79. LONG CheckName(STRPTR *pat, STRPTR name);
  80.  
  81. ULONG start(void)
  82. {
  83.   ULONG ret = RETURN_FAIL;
  84.   struct DosLibrary *dosbase;
  85.  
  86.   SysBase = (*((struct ExecBase **) 4));
  87.   { /* test for WB and reply startup-message */
  88.     struct Process *task;
  89.     if(!(task = (struct Process *) FindTask(0))->pr_CLI)
  90.     {
  91.       WaitPort(&task->pr_MsgPort);
  92.       Forbid();
  93.       ReplyMsg(GetMsg(&task->pr_MsgPort));
  94.       return RETURN_FAIL;
  95.     }
  96.   }
  97.  
  98.   if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
  99.   {
  100.     LONG err = 0;
  101.     struct xadMasterBase *xadmasterbase;
  102.  
  103.     DOSBase = dosbase;
  104.     if((xadmasterbase = (struct xadMasterBase *)
  105.     OpenLibrary("xadmaster.library", 1)))
  106.     {
  107.       struct Args args;
  108.       struct RDArgs *rda;
  109.       
  110.       memset(&args, 0, sizeof(struct Args));
  111.       xadMasterBase = xadmasterbase;
  112.  
  113.       if((rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
  114.       {
  115.         rda->RDA_ExtHelp = OPTIONS;
  116.  
  117.         if(ReadArgs(PARAM, (LONG *) &args, rda))
  118.         {
  119.       if(args.destdir || args.info)
  120.       {
  121.         struct xadArchiveInfo *ai;
  122.     
  123.         if((ai = (struct xadArchiveInfo *)
  124.         xadAllocObjectA(XADOBJ_ARCHIVEINFO, 0)))
  125.         {
  126.           if(!(err = xadGetInfo(ai, XAD_INFILENAME, args.from,
  127.           XAD_NOEXTERN, args.noextern, args.password ? XAD_PASSWORD :
  128.           TAG_IGNORE, args.password, TAG_DONE)))
  129.           {
  130.             if(ai->xai_Flags & XADAIF_FILECORRUPT)
  131.               Printf("!!! The archive file has some corrupt data. !!!\n");
  132.             if(args.info)
  133.             {
  134.               struct xadFileInfo *xfi;
  135.               ULONG grsize = 0;
  136.               Printf("ArchiverName:   %s\n"
  137.           "Size     CrndSize Ratio Date       Time     Name\n",
  138.           ai->xai_Client->xc_ArchiverName);
  139.  
  140.               xfi = ai->xai_FileInfo;
  141.               while(xfi && !CTRL_C)
  142.               {
  143.                 if(!(xfi->xfi_Flags & XADFIF_GROUPED))
  144.                   grsize = 0;
  145.             if(xfi->xfi_Flags & XADFIF_DIRECTORY)
  146.             {
  147.               if(!args.notree)
  148.                     Printf("   <dir>    <dir>       %02ld.%02ld.%04ld %02ld:%02ld:%02ld %s\n",
  149.                     xfi->xfi_Date.xd_Day, xfi->xfi_Date.xd_Month,
  150.                     xfi->xfi_Date.xd_Year, xfi->xfi_Date.xd_Hour,
  151.                     xfi->xfi_Date.xd_Minute, xfi->xfi_Date.xd_Second,
  152.                     xfi->xfi_FileName);
  153.                 }
  154.             else if(xfi->xfi_Flags & XADFIF_GROUPED)
  155.             {
  156.                   Printf("%8ld   merged  n/a  %02ld.%02ld.%04ld %02ld:%02ld:%02ld %s\n",
  157.                   xfi->xfi_Size, xfi->xfi_Date.xd_Day, xfi->xfi_Date.xd_Month,
  158.                   xfi->xfi_Date.xd_Year, xfi->xfi_Date.xd_Hour,
  159.                   xfi->xfi_Date.xd_Minute, xfi->xfi_Date.xd_Second,
  160.                   args.notree ? FilePart(xfi->xfi_FileName) :
  161.                   xfi->xfi_FileName);
  162.                   grsize += xfi->xfi_Size;
  163.                   if(xfi->xfi_Flags & XADFIF_ENDOFGROUP)
  164.                   {
  165.                 ULONG i = 0, j = 0;
  166.               
  167.                 if(xfi->xfi_GroupCrSize < grsize)
  168.                 {
  169.                   i = ((grsize - xfi->xfi_GroupCrSize)*1000)/grsize;
  170.                   j = i % 10;
  171.                   i /= 10;
  172.                 }
  173.                     Printf("%8ld %8ld %2ld.%1ld%%\n", grsize, xfi->xfi_GroupCrSize,
  174.                     i, j);
  175.                     grsize = 0;
  176.                   }
  177.             }
  178.             else
  179.             {
  180.               ULONG i = 0, j = 0;
  181.               
  182.               if(xfi->xfi_CrunchSize < xfi->xfi_Size)
  183.               {
  184.                 i = ((xfi->xfi_Size - xfi->xfi_CrunchSize)*1000)/xfi->xfi_Size;
  185.                 j = i % 10;
  186.                 i /= 10;
  187.               }
  188.                  
  189.                   Printf("%8ld %8ld %2ld.%1ld%% %02ld.%02ld.%04ld %02ld:%02ld:%02ld %s\n",
  190.                   xfi->xfi_Size, xfi->xfi_CrunchSize, i, j,
  191.                   xfi->xfi_Date.xd_Day, xfi->xfi_Date.xd_Month,
  192.                   xfi->xfi_Date.xd_Year, xfi->xfi_Date.xd_Hour,
  193.                   xfi->xfi_Date.xd_Minute, xfi->xfi_Date.xd_Second,
  194.                   args.notree ? FilePart(xfi->xfi_FileName) :
  195.                   xfi->xfi_FileName);
  196.                 }
  197.                 if(xfi->xfi_Comment && !args.nocomment)
  198.                   Printf(": %s\n", xfi->xfi_Comment);
  199. #ifdef DEBUG
  200.             if(xfi->xfi_Flags)
  201.             {
  202.                   Printf("Flags:          ");
  203.                   if(xfi->xfi_Flags & XADFIF_CRYPTED)
  204.                     Printf("XADFIF_CRYPTED ");
  205.                   if(xfi->xfi_Flags & XADFIF_DIRECTORY)
  206.                     Printf("XADFIF_DIRECTORY ");
  207.                   if(xfi->xfi_Flags & XADFIF_LINK)
  208.                     Printf("XADFIF_LINK ");
  209.                   if(xfi->xfi_Flags & XADFIF_INFOTEXT)
  210.                     Printf("XADFIF_INFOTEXT ");
  211.                   if(xfi->xfi_Flags & XADFIF_GROUPED)
  212.                     Printf("XADFIF_GROUPED ");
  213.                   if(xfi->xfi_Flags & XADFIF_ENDOFGROUP)
  214.                     Printf("XADFIF_ENDOFGROUP ");
  215.                   if(xfi->xfi_Flags & XADFIF_NODATE)
  216.                     Printf("XADFIF_NODATE ");
  217.                   Printf("\n");
  218.                 }
  219. #endif
  220.                 if(xfi->xfi_Flags & XADFIF_CRYPTED)
  221.                   Printf("The entry is encrypted\n");
  222.                 xfi = xfi->xfi_Next;
  223.               }
  224.               ret = 0;
  225.             }
  226.             else
  227.             {
  228.           struct Hook prhook;
  229.           struct xadFileInfo *fi;
  230.           UBYTE filename[256];
  231.           struct xHookArgs xh;
  232.         
  233.           ret = 0;
  234.           xh.name = filename;
  235.           xh.flags = xh.finish = 0;
  236.  
  237.               memset(&prhook, 0, sizeof(struct Hook));
  238.               prhook.h_Entry = (ULONG (*)()) progrhook;
  239.               prhook.h_Data = &xh;
  240.           fi = ai->xai_FileInfo;
  241.           while(fi && !CTRL_C && !xh.finish)
  242.           {
  243.             if(!args.file || CheckName(args.file, args.notree ?
  244.             FilePart(fi->xfi_FileName) : fi->xfi_FileName))
  245.             {
  246.               CopyMem(args.destdir, filename, strlen(args.destdir)+1);
  247.               if(args.notree)
  248.                 AddPart(filename, FilePart(fi->xfi_FileName), 256);
  249.               else if(!args.noabs)
  250.                 AddPart(filename, fi->xfi_FileName, 256);
  251.               else
  252.               {
  253.                 STRPTR fname = filename, f;
  254.  
  255.             if(*args.destdir)
  256.             {
  257.                   fname += strlen(args.destdir)-1;
  258.                   if(*fname != ':' && *fname != '/')
  259.                     *(++fname) = '/';
  260.                   ++fname;
  261.                 }
  262.                 for(f = fi->xfi_FileName; *f; ++f)
  263.                   *(fname++) = *f == ':' ? '/' : *f;
  264.                 *fname = 0;
  265.               }
  266.               if(fi->xfi_Flags & XADFIF_DIRECTORY)
  267.               {
  268.                 if(!args.notree)
  269.                 {
  270.                   BPTR a;
  271.                   LONG err = 0, i = 0;
  272.                   UBYTE r;
  273.                   while(filename[i] && !err)
  274.                   {
  275.                       for(;filename[i] && filename[i] != '/'; ++i)
  276.                       ;
  277.                       r = filename[i];
  278.                       filename[i] = 0;
  279.                 if((a = Lock(filename, SHARED_LOCK)))
  280.                         UnLock(a);
  281.                     else if((a = CreateDir(filename)))
  282.                           UnLock(a);
  283.                       else
  284.                           err = 1;
  285.                         filename[i++] = r;
  286.                   }
  287.                   if(err)
  288.                     Printf("failed to create directory '%s'\n",
  289.                     fi->xfi_FileName);
  290.                   else
  291.                     Printf("Created directory   : %s\n", filename);
  292.                 }
  293.               } 
  294.               else if(fi->xfi_Flags & XADFIF_LINK)
  295.               {
  296.                 Printf("Skipped Link\n");
  297.               }
  298.               else
  299.               {
  300.                 struct DateStamp d;
  301.  
  302.                 if(!xadFileUnArc(ai, XAD_OUTFILENAME, filename,
  303.                     XAD_ENTRYNUMBER, fi->xfi_EntryNumber, XAD_MAKEDIRECTORY,
  304.                     !args.askmakedir, XAD_OVERWRITE, args.overwrite,
  305.                     XAD_PROGRESSHOOK, &prhook, TAG_DONE))
  306.                     {
  307.                       if(!args.nodate && !(fi->xfi_Flags & XADFIF_NODATE)
  308.                       && !xadConvertDates(XAD_DATEXADDATE, &fi->xfi_Date,
  309.                       XAD_GETDATEDATESTAMP, &d, TAG_DONE))
  310.                         SetFileDate(filename, &d);
  311.                       if(!args.noprot)
  312.                         SetProtection(filename, fi->xfi_Protection);
  313.                       if(fi->xfi_Comment && !args.nocomment)
  314.                         SetComment(filename, fi->xfi_Comment);
  315.                       /* SetOwner ??? */
  316.                     }
  317.                   }
  318.                 }
  319.                 fi = fi->xfi_Next;
  320.               }
  321.             }
  322.             xadFreeInfo(ai);
  323.           } /* xadGetInfo */
  324.  
  325.           xadFreeObjectA(ai, 0);
  326.             } /* xadAllocObject */
  327.           }
  328.           else
  329.             SetIoErr(ERROR_REQUIRED_ARG_MISSING);
  330.  
  331.           FreeArgs(rda);
  332.         } /* ReadArgs */
  333.         FreeDosObject(DOS_RDARGS, rda);
  334.       } /* AllocDosObject */
  335.  
  336.       if(CTRL_C)
  337.         SetIoErr(ERROR_BREAK);
  338.  
  339.       if(err)
  340.     Printf("An error occured: %s\n", xadGetErrorText(err));
  341.       else if(ret)
  342.         PrintFault(IoErr(), 0);
  343.  
  344.       CloseLibrary((struct Library *) xadmasterbase);
  345.     } /* OpenLibrary xadmaster */
  346.     else
  347.       Printf("Could not open xadmaster.library\n");
  348.     CloseLibrary((struct Library *) dosbase);
  349.   } /* OpenLibrary dos */
  350.   return ret;
  351. }
  352.  
  353. /* Because of SAS-err, this cannot be SAVEDS */
  354. ASM(ULONG) progrhook(REG(a0, struct Hook *hook),
  355. REG(a1, struct xadProgressInfo *pi))
  356. {
  357.   ULONG ret = 0;
  358.   STRPTR name = ((struct xHookArgs *) (hook->h_Data))->name;
  359.  
  360.   switch(pi->xpi_Mode)
  361.   {
  362.   case XADPMODE_ASK:
  363.     ret |= ((struct xHookArgs *) (hook->h_Data))->flags;
  364.     if((pi->xpi_Status & XADPIF_OVERWRITE) && !(ret & XADPIF_OVERWRITE))
  365.     {
  366.       Printf("File '%s' already exists, overwrite? (Y|A|S|\033[1mN\033[0m|Q): ",
  367.       name);
  368.       Flush(Output());
  369.       SetMode(Input(), TRUE);
  370.       switch(FGetC(Input()))
  371.       {
  372.       case 'a': case 'A':
  373.     ((struct xHookArgs *) (hook->h_Data))->flags |= XADPIF_OVERWRITE;
  374.       case 'y': case 'Y': ret |= XADPIF_OVERWRITE; break;
  375.       case 's': case 'S': ret |= XADPIF_SKIP; break;
  376.       case 'q': case 'Q': ((struct xHookArgs *) (hook->h_Data))->finish = 1;
  377.       }
  378.       SetMode(Input(), FALSE);
  379.     }
  380.     if((pi->xpi_Status & XADPIF_MAKEDIRECTORY) &&
  381.     !(ret & XADPIF_MAKEDIRECTORY))
  382.     {
  383.       Printf("Directory of file '%s' does not exist, create? (Y|A|S|\033[1mN\033[0m|Q): ",
  384.       name);
  385.       Flush(Output());
  386.       SetMode(Input(), TRUE);
  387.       switch(FGetC(Input()))
  388.       {
  389.       case 'a': case 'A':
  390.     ((struct xHookArgs *) (hook->h_Data))->flags |= XADPIF_MAKEDIRECTORY;
  391.       case 'y': case 'Y': ret |= XADPIF_MAKEDIRECTORY; break;
  392.       case 's': case 'S': ret |= XADPIF_SKIP; break;
  393.       case 'q': case 'Q': ((struct xHookArgs *) (hook->h_Data))->finish = 1;
  394.       }
  395.       SetMode(Input(), FALSE);
  396.     }
  397.     break;
  398.   case XADPMODE_PROGRESS:
  399.     Printf("\r\033[KWrote %8ld of %8ld bytes: %s",
  400.     pi->xpi_CurrentSize, pi->xpi_FileInfo->xfi_Size, name);
  401.     Flush(Output());
  402.     break;
  403.   case XADPMODE_END: Printf("\r\033[KWrote %8ld bytes: %s\n",
  404.     pi->xpi_CurrentSize, name);
  405.     break;
  406.   case XADPMODE_ERROR: Printf("\r\033[K%s: %s\n", name,
  407.     xadGetErrorText(pi->xpi_Error));
  408.     break;
  409.   }
  410.  
  411.   if(!CTRL_C) /* clear ok flag */
  412.     ret |= XADPIF_OK;
  413.  
  414.   return ret;
  415. }
  416.  
  417. /* would be better to store the pattern parse stuff and do it only once,
  418. but so it is a lot easier */
  419. LONG CheckName(STRPTR *pat, STRPTR name)
  420. {
  421.   UBYTE buf[500];
  422.   while(*pat)
  423.   {
  424.     if(ParsePatternNoCase(*(pat++), buf, 500) >= 0)
  425.     {
  426.       if(MatchPatternNoCase(buf, name))
  427.         return 1;
  428.     } /* A scan failure means no recognition, should be an error print here */
  429.   }
  430.   return 0;
  431. }
  432.